#include <jni.h>
#include "Verification.h"
#include <iostream>
#include <string>
#include "MD5.h"
#include "Log.h"

Verification::Verification(JNIEnv *env, jobject contextObject) {
    this->env = env;
    this->contextObject = contextObject;

}


Verification::~Verification() {
}

std::string Verification::getSign() {
    if (this->env == NULL || this->contextObject == NULL) {
        return "";
    } else {
        jclass native_class = env->GetObjectClass(contextObject);
        if(native_class == 0){
            return "";
        }
        jmethodID pm_id = env->GetMethodID(native_class, "getPackageManager",
                                           "()Landroid/content/pm/PackageManager;");
        if (pm_id == nullptr){
            return "";
        }
        env->DeleteLocalRef(native_class);
        jobject pm_obj = env->CallObjectMethod(contextObject, pm_id);
        jclass pm_clazz = env->GetObjectClass(pm_obj);
        if (pm_clazz == nullptr){
            return "";
        }
        // 得到 getPackageInfo 方法的 ID
        jmethodID package_info_id = env->GetMethodID(pm_clazz, "getPackageInfo",
                                                     "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
        if (package_info_id == nullptr){
            return "";
        }
        env->DeleteLocalRef(pm_clazz);
        jclass native_classs = env->GetObjectClass(contextObject);
        if (native_classs == 0){
            return "";
        }
        jmethodID mId = env->GetMethodID(native_classs, "getPackageName", "()Ljava/lang/String;");
        if (mId == 0){
            return "";
        }
        env->DeleteLocalRef(native_classs);
        jstring pkg_str = static_cast<jstring>(env->CallObjectMethod(contextObject, mId));
        // 获得应用包的信息
        jobject pi_obj = env->CallObjectMethod(pm_obj, package_info_id, pkg_str, 64);
        env->DeleteLocalRef(pkg_str);
        env->DeleteLocalRef(pm_obj);
        // 获得 PackageInfo 类
        jclass pi_clazz = env->GetObjectClass(pi_obj);
        if (pi_clazz == 0){
            return "";
        }
        // 获得签名数组属性的 ID
        jfieldID signatures_fieldId = env->GetFieldID(pi_clazz, "signatures",
                                                      "[Landroid/content/pm/Signature;");
        if (signatures_fieldId == 0){
            return "";
        }
        env->DeleteLocalRef(pi_clazz);

        jobjectArray signaturesArray = (jobjectArray) env->GetObjectField(pi_obj, signatures_fieldId);
        env->DeleteLocalRef(pi_obj);
        jsize size = env->GetArrayLength(signaturesArray);
        jobject signature_obj = env->GetObjectArrayElement(signaturesArray, 0);
        env->DeleteLocalRef(signaturesArray);
        jclass signature_clazz = env->GetObjectClass(signature_obj);
        if (signature_clazz == 0){
            return "";
        }
        jmethodID string_id = env->GetMethodID(signature_clazz, "toCharsString",
                                               "()Ljava/lang/String;");
        if (string_id == 0){
            return "";
        }
        env->DeleteLocalRef(signature_clazz);
        jstring str = static_cast<jstring>(env->CallObjectMethod(signature_obj, string_id));
        env->DeleteLocalRef(signature_obj);
        std::string sign = (char *) env->GetStringUTFChars(str, 0);
//        Log("签名字符串:%s", sign.c_str());
        return sign;
    }

}

bool Verification::isEqual() {
    const std::string str = md5(getSign());
//    Log("获取的签名为:%s", str.c_str());
    std::string starSign = "3e0e8620013c65d0380080270b2d5455";
    int compareResult = str.compare(getReleaseSign(starSign, RELEASE_SIGN_MD5_END));
    if (compareResult == 0) {
//        Log("签名验证通过");
        return true;
    } else {
//        Log("签名验证失败");
        return false;
    }
}

std::string getReleaseSign(std::string startStr, std::string endStr) {
    long sl = startStr.size();
    long el = endStr.size();
    if (sl == 32 && el == 32) {
        std::string temps = "";
        std::string tempe = "";
        for (int i = 0; i < 32; i++) {
            if (i % 2 == 0) {
                tempe += endStr[i];
            } else {
                temps += startStr[i];
            }
        }
        return temps + tempe;
    } else {
        return "null";
    }
}

bool verification(JNIEnv *env, jobject contextObject) {
    Verification v = Verification(env, contextObject);
    return v.isEqual();
}

jstring checkAndReturn32(JNIEnv *env, const std::string startStr, const std::string endStr,
                         const jobject contextObject) {
    bool isSelf = verification(env, contextObject);
//	Log("验证结果:%d",isSelf);
    if (isSelf) {
        return env->NewStringUTF(getReleaseSign(startStr, endStr).c_str());
    } else {
        return env->NewStringUTF("error");
    }
}

jstring checkAndReturn(JNIEnv *env, const std::string startStr, const std::string endStr,
                       const std::string surplusStr, const jobject contextObject) {

    bool isSelf = verification(env, contextObject);
//	Log("验证结果:%d",isSelf);
    if (isSelf) {
        std::string sStr = getReleaseSign(startStr, endStr)+surplusStr;
        return env->NewStringUTF(sStr.c_str());
    } else {
        return env->NewStringUTF("error");
    }
}

